package com.hbsc.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.HostnameVerifier;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by xudong on 2017-11-02.
 */
@Component
public class WechartUtil {

    @Value("${wx.tokenurl}")
    public String tokenurl;
    @Value("${wx.accesstokenurl}")
    public String accesstokenurl;
    @Value("${wx.appid}")
    public String appid;
    @Value("${wx.secret}")
    public String secret;
    @Value("${wx.userInfoUrl}")
    public String userInfoUrl;
    @Value("${wx.refreshtokenurl}")
    public String refreshTokenUrl;
    @Value("${wx.codeurl}")
    public String codeurl;

    private static final HostnameVerifier PROMISCUOUS_VERIFIER = (s, sslSession ) -> true;

    private static Map tokenMap;

    private Map doGet(String requestUrl) throws IOException {
        HttpClientUtil util=new HttpClientUtil();
        String retStr=util.doGet(requestUrl,"UTF-8");
        ObjectMapper mapper = new ObjectMapper();
        Map map=mapper.readValue(retStr,Map.class);
        return map;
    }

    private void token(){
        RestTemplate rest=RestTemplateUtil.getRestTemplateSsl();
        Map<String,String> arg=new HashMap<>();
        StringBuffer requestUrl=new StringBuffer(tokenurl);
        requestUrl.append("?grant_type=client_credential&appid=").append(appid).append("&secret=").append(secret);
        Map map=rest.getForObject(requestUrl.toString(), Map.class);
        String accessToken= String.valueOf(map.get("access_token"));
        Long expiresIn=Long.valueOf(String.valueOf(map.get("expires_in")));
        Long expiresOut=(new Date()).getTime()+(expiresIn*1000);
        if(null==tokenMap){
            tokenMap=new HashMap<>();
        }
        tokenMap.put("accessToken",accessToken);
        tokenMap.put("expiresOut",expiresOut);
    }

    private Map accessToken(String code) throws IOException {
        //RestTemplate rest=RestTemplateUtil.getRestTemplateSsl();

        Map<String,String> arg=new HashMap<>();
        StringBuffer requestUrl=new StringBuffer(accesstokenurl);
        requestUrl.append("?appid=").append(appid)
                .append("&secret=").append(secret)
                .append("&code=").append(code)
                .append("&grant_type=authorization_code");
        return doGet(requestUrl.toString());
    }
    private Map refreshToken(String refreshToken)throws IOException{
        Map<String,String> arg=new HashMap<>();
        StringBuffer requestUrl=new StringBuffer(refreshTokenUrl);
        requestUrl.append("?appid=").append(appid).append("&grant_type=refresh_token&refresh_token=").append(refreshToken);
        return doGet(requestUrl.toString());
    }

    private Map userInfo(String accessToken,String openId) throws IOException {
        HttpClientUtil util=new HttpClientUtil();
        StringBuffer requestUrl=new StringBuffer(userInfoUrl);
        requestUrl.append("?access_token=").append(accessToken)
                .append("&openid=").append(openId)
                .append("&lang=zh_CN");
        return doGet(requestUrl.toString());
    }

    /**
     * 获取Token
     * @return
     */
    public  String getToken(){
        if(null==tokenMap){
            token();
        }
        Long expiresOut=Long.valueOf(String.valueOf(tokenMap.get("expiresOut")));
        if((new Date()).getTime()+(2*60*1000)>=expiresOut){//两分钟内会失效就重新获取
            token();
        }
        return String.valueOf(tokenMap.get("accessToken"));
    }

    /**
     * 获取访问Token
     * @param code
     * @return
     * @throws IOException
     */
    public Map getAccessToken(String code) throws IOException {
       return accessToken(code);
    }
    /**
     * 刷新访问Token
     * @param refreshToken
     * @return
     * @throws IOException
     */
    public Map getRefreshToken(String refreshToken)throws IOException {
        return refreshToken(refreshToken);
    }
    /**
     * 获取用户基础信息
     * @param accessToken
     * @param openId
     * @return
     * @throws IOException
     */
    public Map getUserInfo(String accessToken,String openId) throws IOException {
        return userInfo(accessToken,openId) ;
    }

    public String codeLink(String url) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder(codeurl);
        sb.append("?appid=").append(appid);
        sb.append("&redirect_uri=").append(URLEncoder.encode(url, "utf-8"));
        sb.append("&response_type=code&scope=snsapi_userinfo&state=STATE&connect_redirect=1#wechat_redirect");
        return sb.toString();
    }
}
